ShowTable of Contents
Using LotusScript C-Callouts on non-32-bit Platforms
There are a few issues you need to be aware of if you're writing or porting LotusScript C-Callouts to non-32-bit platforms.
The non-32-bit platforms fall into two categories: 64-bit (Windows 64, AIX-64, Linux-64) and 128-bit (iSeries)
When is a long not a long?
An important thing to consider is that LotusScript data types are the same size across all platforms. A LotusScript
byte is always one byte (a Notes
BYTE in C),
integer is always 2 bytes (a Notes
WORD in C) and a
long is always 4 bytes (a Notes
DWORD in C). In contrast, a C
long is not a fixed width across platforms, or even compilers. In the Notes 8 builds, a long is 4 bytes on Windows-64 and iSeries, but 8 bytes on AIX-64, SUSE Linux-64 and zLinux64.
In order to check how many bytes a long and a pointer is on a given platform, compile and run the following simple C program:
main()
{
printf("sizeof long is: %d, pointer is %d\n", sizeof (long), sizeof (long *));
}
LotusScript will take care of expanding C-Callout parameters that are 8-byte longs when passed by value, so a LotusScript long (4 bytes) will be expanded in the call to a native long (4 or 8-bytes). However, if you pass a value ByRef where the C-Callout is expecting an pointer to an 8-byte long, then you have to be very careful. The C-Callout (long *) will expect to be pointing to an 8-byte value, when in fact it's pointing to only 4 bytes (for a LotusScript long) allocated by LotusScript. Dereferencing the C-Callout 8-byte-long pointer can result in a memory overwrite that could result in a crash. You can partially get around that by passing a ByRef double LotusScript value to a (long *) C value (on platforms where a long is 8 bytes) since LotusScript will have allocated 8-bytes (the size of a LotusScript double) to point to. Then, on the C side, dereferencing the (long *) value will not cause a crash. However, on the LotusScript side you will not be able to reference or modify the double that was passed ByRef, since internally it's a different format than an 8-byte long. You can, however, pass it to another C-Callout that expects an 8-byte long value.
As an aside, a Notes
DHANDLE is 32 bits on all platforms except Solaris and AIX-32, where it's 16 bits.
There were some bugs in C-Callouts on 64-bit platforms that have been fixed in Notes/Domino 8.5.2.
Pointers
Pointers are a more straightforward issue (except on iSeries). On all 64-bit platforms, you can pass and return 8-byte pointers by using the LotusScript
double datatype. However, you
cannot manipulate these objects on the LotusScript side. Your C-Callout can return a pointer in a double, and then in LotusScript you can call another C-Callout with the double parameter to a C pointer, but you must not change the value of the double in LotusScript. This is the same scheme you can use to pass a pointer to an 8-byte long integer value described above.
In order to be able to return the pointer in double you need to set environment variable LS64BITCCALLOUTPointerSupport=1
iSeries has it's own issue in that pointers are 16-bytes long. Since no LotusScript data type is that big, you cannot pass pointers by value or return pointers via C-Callouts on iSeries. Passing pointers by reference works well, however without being able to obtain them by value using functions such as OSMemoryLock it does not help much.
In addition C_Callout implementation on iSeries simply does not work for any functions passing parameters by value. This might be caused by the fact that historically Domino on iSeries has been compiled with wrong linking conventions and to keep existing C applications that link to Domino from breaking, the product management have decided rather to stick with the bug than to enable C-Callouts work properly.